package keer.httpinterface.http;

import keer.httpinterface.utils.IOUtils;
import keer.httpinterface.utils.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * 封装http响应消息的封装类
 * @see HttpConnection
 *
 * @author Keer
 * @since 1.0.0
 */
public class HttpResponse {
    private int statusCode;
    private InputStream content;
    private InputStream error;
    private final Headers headers;
    private String message;
    private long contentLength;
    private String contentEncoding;
    private String contentType;
    private HttpConnection connection;
    private String version;

    private HttpResponse() {
        this.headers = new Headers();
    }

    /**
     * 获取响应状态码
     * @return 响应状态码
     */
    public int getStatusCode() {
        return statusCode;
    }

    /**
     * 获取响应内容
     * @return 响应内容
     */
    public InputStream getContent() {
        return content;
    }

    /**
     * 获取响应错误内容
     * @return 响应错误内容
     */
    public InputStream getError() {
        return error;
    }

    /**
     * 获取响应头
     * @return 响应头
     */
    public Headers getHeaders() {
        return headers;
    }

    /**
     * 获取响应消息
     * @return 响应消息
     */
    public String getMessage() {
        return message;
    }

    /**
     * 获取响应内容
     * @return 响应内容
     * @throws IOException 读取响应内容异常
     */
    public byte[] bytes() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        IOUtils.copy(content, bos);
        return bos.toByteArray();
    }

    /**
     * 获取文本类型的响应内容
     * @return 文本类型的响应内容
     * @throws IOException 读取响应内容异常
     */
    public String text() throws IOException {
        String charset = headers.contentType() == null ? StandardCharsets.UTF_8.name() : headers.contentType().getCharset();
        return IOUtils.readText(content, charset);
    }

    /**
     * 响应构建器，用于构建响应对象
     * @see HttpResponse
     *
     * @author Keer
     * @since 1.0.0
     */
    public static class Builder {
        private final HttpResponse response;

        private Builder() {
            response = new HttpResponse();
        }

        /**
         * 设置响应状态码
         * @param statusCode 响应状态码
         * @return Builder
         */
        public Builder statusCode(int statusCode) {
            response.statusCode = statusCode;
            return this;
        }

        /**
         * 设置响应内容
         * @param content 响应内容
         * @return Builder
         */
        public Builder content(InputStream content) {
            response.content = content;
            return this;
        }

        /**
         * 设置响应错误内容
         * @param content 响应错误内容
         * @return Builder
         */
        public Builder error(InputStream content) {
            response.error = content;
            return this;
        }

        /**
         * 设置响应头
         * @param headers 响应头
         * @return Builder
         */
        public Builder headers(Headers headers) {
            this.response.headers.putAll(headers);
            return this;
        }

        /**
         * 设置响应头
         * @param key 响应头的key
         * @param header 响应头的value
         * @return Builder
         */
        public Builder header(String key, String header) {
            this.response.headers.put(key, header);
            return this;
        }

        /**
         * 设置响应消息
         * @param message 响应消息
         * @return Builder
         */
        public Builder message(String message) {
            this.response.message = message;
            return this;
        }

        /**
         * 设置响应内容长度
         * @param contentLength 响应内容长度
         * @return Builder
         */
        public Builder contentLength(long contentLength) {
            this.response.contentLength = contentLength;
            return this;
        }

        /**
         * 设置响应内容编码
         * @param contentEncoding 响应内容编码
         * @return Builder
         */
        public Builder contentEncoding(String contentEncoding) {
            this.response.contentEncoding = contentEncoding;
            return this;
        }

        /**
         * 设置响应内容类型
         * @param contentType 响应内容类型
         * @return Builder
         */
        public Builder contentType(String contentType) {
            this.response.contentType = contentType;
            return this;
        }

        /**
         * 构建一个{@link HttpResponse}对象
         * @return HttpResponse
         */
        public HttpResponse build() {
            return response;
        }

        /**
         * 设置连接
         * @param connection 连接对象
         * @return Builder
         */
        public Builder connection(HttpConnection connection) {
            this.response.connection = connection;
            return this;
        }

        /**
         * 设置http请求版本
         * @param version http请求版本，默认为HTTP/1.1
         * @return Builder
         */
        public Builder version(String version) {
            this.response.version = version;
            return this;
        }
    }

    /**
     * 构建一个响应构建器
     * @return Builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * 获取响应内容长度
     * @return 响应内容长度
     */
    public long getContentLength() {
        return contentLength;
    }

    /**
     * 获取响应内容编码
     * @return 响应内容编码
     */
    public String getContentEncoding() {
        return contentEncoding;
    }

    /**
     * 获取响应内容类型
     * @return 响应内容类型
     */
    public String getContentType() {
        return contentType;
    }

    /**
     * 关闭连接
     * @throws Exception 关闭连接异常
     */
    public void closeConnection() throws Exception {
        if (connection != null) {
            connection.close();
        }
    }

    @Override
    public String toString() {
        return "Response:" +
                statusCode +
                " " + (StringUtils.isBlank(version) ? "" : version) +
                " " + (StringUtils.isBlank(message) ? "" : message) +
                "\n" +
                headers;
    }

//    public static class ResponseContent extends  InputStream {
//        private final InputStream input;
//        private volatile long available;
//        private volatile long read;
//
//        public ResponseContent(InputStream input) throws IOException {
//            this.input = input;
//            this.read = 0;
//            if (input == null) {
//                this.available = 0;
//            } else {
//                this.available = input.available();
//            }
//        }
//
//
//        @Override
//        public int read() throws IOException {
//            if (read >= available) {
//                return -1;
//            }
//            read ++;
//            return input.read();
//        }
//
//    }
}
